﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.IO;
using System.Diagnostics;
using System.Reflection;
using PSE.Framework.Threading;

namespace Sinacor.OMM.Util
{

    public class Tracer
    {
        private const int TIME_TO_CHECK_OPTIONAL_TRACE_ENABLED = 2000;
        private const string CLSID = "A72AE7BA-08D5-4209-8774-358F80580AD1";

        private static Dictionary<string, TraceWriter> _dctLogServer;
        private static bool _closing;
        private static bool _optionalTraceEnabled;

        private Tracer()
        {
            _optionalTraceEnabled = OptionalTraceEnabledFileRead();
        }

        public static TraceWriter GetInstance(string folderName, string filename)
        {
            if (!_closing)
            {
                try
                {

                    if (_dctLogServer == null)
                    {
                        _dctLogServer = new Dictionary<string, TraceWriter>();
                        Thread thr = new Thread(new ThreadStart(OptionalTraceEnabledMonitor));
                        thr.Name = "Monitora trace habilitado";
                        thr.Start();
                    }

                    lock (_dctLogServer)
                    {
                        TraceWriter ret;
                        if (_dctLogServer.ContainsKey(folderName + filename))
                            ret = _dctLogServer[folderName + filename];
                        else
                        {
                            ret = new TraceWriter(folderName, filename, CLSID)
                            {
                                OptionalTraceEnabled = _optionalTraceEnabled
                            };
                            _dctLogServer.Add(folderName + filename, ret);
                        }
                        return ret;
                    }
                }
                catch (Exception ex)
                {
                    EventLog.WriteEntry("Tracer", ex.Message);
                    EventLog.WriteEntry("Tracer", ex.StackTrace);
                    return null;
                }
            }
            else
                return null;
        }

        private static void OptionalTraceEnabledMonitor()
        {

            bool lastOptionalTraceEnabled = false;

            while (!_closing)
            {
                try
                {
                    _optionalTraceEnabled = OptionalTraceEnabledFileRead();

                    if (lastOptionalTraceEnabled != _optionalTraceEnabled)
                    {
                        if (_dctLogServer != null)
                        {
                            lock (_dctLogServer)
                            {
                                foreach (TraceWriter logWriter in _dctLogServer.Values)
                                {
                                    logWriter.OptionalTraceEnabled = _optionalTraceEnabled;
                                }
                            }
                        }
                    }

                    lastOptionalTraceEnabled = _optionalTraceEnabled;
                    Sleeper.Sleep(TIME_TO_CHECK_OPTIONAL_TRACE_ENABLED, () => !_closing);
                }
                catch (Exception ex)
                {
                    EventLog.WriteEntry("Tracer", ex.Message);
                    EventLog.WriteEntry("Tracer", ex.StackTrace);
                }
            }
        }

        private static bool OptionalTraceEnabledFileRead()
        {
            string FILE_NAME = string.Concat(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), Path.DirectorySeparatorChar, "Trace.ini");
            const string TAGNAME = "TraceEnabled";

            bool ret;

            try
            {
                if (!File.Exists(FILE_NAME))
                {
                    File.WriteAllText(FILE_NAME, TAGNAME + "=0");
                    ret = false;
                }
                else
                {
                    try
                    {

                        string fileContent = File.ReadAllText(FILE_NAME);
                        int idxValorTraceEnabled = fileContent.IndexOf(TAGNAME) + TAGNAME.Length;
                        string value = fileContent.Substring(idxValorTraceEnabled, fileContent.Length - idxValorTraceEnabled);
                        value = value.Replace(" ", string.Empty);
                        value = value.Replace("=", string.Empty);
                        value = value.Replace("\r\n", string.Empty);
                        if (int.Parse(value) == 0)
                            ret = false;
                        else
                            ret = true;
                    }
                    catch (Exception ex)
                    {
                        if (!File.Exists(FILE_NAME))
                        {
                            File.Delete(FILE_NAME);
                            File.WriteAllText(FILE_NAME, TAGNAME + "=0");
                        }
                        ret = false;
                    }
                }
            }
            catch (Exception ex)
            {
                EventLog.WriteEntry("Tracer","Não conseguiu ler arquivo de Trace");
                EventLog.WriteEntry("Tracer","Arquivo: [" + FILE_NAME + "]");
                EventLog.WriteEntry("Tracer",ex.Message);
                EventLog.WriteEntry("Tracer",ex.StackTrace);
                ret = false;
            }

            return ret;
        }

        public static void RemoveInstance(string folderName, string filename)
        {
            try
            {
                if (_dctLogServer != null)
                {
                    lock (_dctLogServer)
                    {
                        _dctLogServer[folderName + filename].Close();
                        _dctLogServer.Remove(folderName + filename);
                    }
                }
            }
            catch (Exception ex)
            {
                EventLog.WriteEntry("Tracer", ex.Message);
                EventLog.WriteEntry("Tracer", ex.StackTrace);
            }
        }

        public static void Destroy()
        {
            try
            {
                _closing = true;

                if (_dctLogServer != null)
                {
                    lock (_dctLogServer)
                    {
                        foreach (TraceWriter logWriter in _dctLogServer.Values)
                        {
                            logWriter.Close();
                        }
                        _dctLogServer.Clear();
                    }
                }
            }
            catch (Exception ex)
            {
                EventLog.WriteEntry("Tracer", ex.Message);
                EventLog.WriteEntry("Tracer", ex.StackTrace);
            }
        }
    }
}
